package cn.whdreamblog.daoimp;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.Query;

import com.sun.istack.internal.NotNull;

import cn.whdreamblog.util.MyDBUtil;
/**
 * 
 * @author Administrator
 * 所有的dao实现类的基类
 */
public class BaseModelDAOImp {
	protected SessionFactory sessionFactory;
	protected Session session;
	protected Transaction tx;
	protected Logger LOG = Logger.getLogger(getClass());
	public BaseModelDAOImp() {
		try {
			sessionFactory = MyDBUtil.getSessionFactory();
		} catch (Exception e) {
			LOG.error(this.getClass().getSimpleName()+":",e);
			e.printStackTrace();
		}
	}

	public boolean insertData(Object data) {
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				tx = session.beginTransaction();
				session.save(data);
				tx.commit();
				return true;
			} catch (Exception e) {
				LOG.error("insertData:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return false;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public boolean removeData(Object data) {
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				Class clazz = data.getClass();
				Method method = clazz.getMethod("getId");
				int id = (Integer) method.invoke(data);
				tx = session.beginTransaction();
				session.delete(session.get(clazz, id));
				tx.commit();
				return true;
			} catch (Exception e) {
				LOG.error("removeData:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return false;

	}

	public <T> T getDataById(T data) {
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				Class clazz = data.getClass();
				Method method = clazz.getMethod("getId");
				int id = (Integer) method.invoke(data);
				T temp = null;
				tx = session.beginTransaction();
				temp = (T) session.get(clazz, id);
				tx.commit();
				if (temp != null) {
					return temp;
				}

			} catch (Exception e) {
				LOG.error("getDataById:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return null;
	}
	
	public <T> T getDataById(int id,Class cls) {
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				T temp = null;
				tx = session.beginTransaction();
				T t = (T) session.get(cls, id);
				temp = t;
				tx.commit();
				if (temp != null) {
					return temp;
				}

			} catch (Exception e) {
				LOG.error("getDataById:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return null;
	}
	/**
	 * 
	 * @param id
	 * @param className
	 * @param attrName
	 * @param attrValue
	 * @param isUseAnd 构建hql是否使用and连接，默认使用or
	 * @return
	 */
	public <T> List<T> getDatasByAttr(@NotNull String className,@NotNull String[] attrName , @NotNull String[] attrValue ,boolean isUseAnd ) {
		if (sessionFactory != null&& attrName.length == attrValue.length ) {
			String hql =creatWhereHql(className, attrName, attrValue, isUseAnd);
			session = sessionFactory.openSession();
			try {
				
				tx = session.beginTransaction();
				@SuppressWarnings("unchecked")
				List<T>	temp =(List<T>)session.createQuery(hql).list();
				tx.commit();
				if (temp != null&& temp.size()>0) {
					return temp;
				}

			} catch (Exception e) {
				LOG.error("getDatasByAttr:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}else{
			throw new RuntimeException("BaseModelDAOImp:sessionFactory为空 or attrName，attrValue长度不相等");
		}
		return null;
	}
	/**
	 * 通过数组创建hql 
	 * 注：下一版本应加入对值的正则表达式判断，防止sql注入,以及判断排序，目前默认id降序
	 * @param className
	 * @param attrName
	 * @param attrValue
	 * @param isUseAnd
	 * @return
	 */
	protected String creatWhereHql(@NotNull String className,@NotNull String[] attrName , @NotNull String[] attrValue , boolean isUseAnd) {
		String hql =MyDBUtil._FROM.concat(className).concat(MyDBUtil._WHERE);
		StringBuilder sb = new StringBuilder();
		if(isUseAnd){
			for (int i = 0; i < attrValue.length; i++) {
				if(i == attrValue.length - 1){
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._ORDER_BY)
					.append(MyDBUtil._id)
					.append(MyDBUtil._DESC);
				}else{
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._AND);
				}
				
			}
		}else{
			for (int i = 0; i < attrValue.length; i++) {
				if(i == attrValue.length - 1){
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._ORDER_BY)
					.append(MyDBUtil._id)
					.append(MyDBUtil._DESC);
				}else{
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._OR);
				}
			}
		}
		return hql.concat(sb.toString());
		
	}
	protected String creatWhereHql(@NotNull String[] attrName , @NotNull String[] attrValue , boolean isUseAnd) {
		StringBuilder sb = new StringBuilder();
		sb.append(MyDBUtil._WHERE);
		if(isUseAnd){
			for (int i = 0; i < attrValue.length; i++) {
				if(i == attrValue.length - 1){
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._ORDER_BY)
					.append(MyDBUtil._id)
					.append(MyDBUtil._DESC);
				}else{
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._AND);
				}
				
			}
		}else{
			for (int i = 0; i < attrValue.length; i++) {
				if(i == attrValue.length - 1){
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._ORDER_BY)
					.append(MyDBUtil._id)
					.append(MyDBUtil._DESC);
				}else{
					sb.append(attrName[i])
					.append(MyDBUtil._EQUALS)
					.append(attrValue[i])
					.append(MyDBUtil._OR);
				}
			}
		}
		return sb.toString();
		
	}
	/**
	 * 直接获取一定量数据
	 * @param start
	 * @param limit
	 * @param className
	 * @return
	 */
	public <T> List<T> getSomeData(int start, int limit, String className) {

		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			Query query = null;
			try {
				tx = session.beginTransaction();
				Long count = getDataCount(session, className);
				query = session.createQuery("from " + className
						+ " order by id desc");
				if (count > limit) {
					query.setFirstResult(start);
					query.setMaxResults(limit);
				}
				List<T> list = query.list();
				tx.commit();
				if (list != null && list.size() > 0) {
					return list;
				}

			} catch (Exception e) {
				LOG.error("getSomeData:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return null;
	}
	
	public <T> Map getSomeData2Map(int start, int limit, String className) {
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			Query query = null;
			try {
				tx = session.beginTransaction();
				Long count = getDataCount(session, className);
				query = session.createQuery("from " + className
						+ " order by id desc");
				if (count > limit) {
					query.setFirstResult(start);
					query.setMaxResults(limit);
				}
				List<T> list = query.list();
				tx.commit();
				if (list != null && list.size() > 0) {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("count", count);
					map.put("list", list);
					return map;
				}

			} catch (Exception e) {
				LOG.error("getSomeData2Map:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return null;
	}
	
	/**
	 * 根据条件获取一定量的数据
	 * @param start
	 * @param limit
	 * @param className
	 * @param attrName
	 * @param attrValue
	 * @param isUseAnd
	 * @return
	 */
	
	public <T> List<T> getSomeData(int start, int limit, String className,@NotNull String[] attrName , @NotNull String[] attrValue , boolean isUseAnd) {
		String hql =creatWhereHql(className, attrName, attrValue, isUseAnd);
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			Query query = null;
			try {
				tx = session.beginTransaction();
				Long count = (Long) session.createQuery(
						"select count(*)" + hql)// 统计条数
						.uniqueResult();
				query = session.createQuery(hql);
				if (count > limit) {
					query.setFirstResult(start);
					query.setMaxResults(limit);
				}
				List<T> list = query.list();
				tx.commit();
				if (list != null && list.size() > 0) {
					return list;
				}

			} catch (Exception e) {
				LOG.error("getSomeData:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return null;
	}
	public <T> Map getSomeData2Map(int start, int limit, String className,@NotNull String[] attrName , @NotNull String[] attrValue , boolean isUseAnd) {
		String hql =creatWhereHql(className, attrName, attrValue, isUseAnd);
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			Query query = null;
			try {
				tx = session.beginTransaction();
				Long count = (Long) session.createQuery(
						"select count(*)" + hql)// 统计条数
						.uniqueResult();
				query = session.createQuery(hql);
				if (count > limit) {
					query.setFirstResult(start);
					query.setMaxResults(limit);
				}
				List<T> list = query.list();
				tx.commit();
				if (list != null && list.size() > 0) {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("count", count);
					map.put("list", list);
					return map;
					
				}

			} catch (Exception e) {
				LOG.error("getSomeData2Map:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return null;
	}
	/**
	 * 统计一定属性筛选后的数量
	 * @param session
	 * @param className
	 * @param attrName
	 * @param attrValue
	 * @param isUseAnd
	 * @return
	 */
	protected Long getDataCount(Session session ,@NotNull String className,@NotNull String[] attrName , @NotNull String[] attrValue , boolean isUseAnd) {
		String hql =MyDBUtil._SELECT.concat("count(*)").concat(creatWhereHql(className, attrName, attrValue, isUseAnd));
		Long count = (Long) session.createQuery(hql)// 统计条数
				.uniqueResult();
		return count;
	}
	
	protected Long getDataCount(@NotNull String className,@NotNull String[] attrName , @NotNull String[] attrValue , boolean isUseAnd) {
		Long count = (long) 0;
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				tx = session.beginTransaction();
			 count = (Long)getDataCount(session ,className,attrName , attrValue ,isUseAnd);
			
			} catch (Exception e) {
				LOG.error("getDataCount:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		
		return count;
	}
	
	protected Long getDataCount(@NotNull String className) {
			Long count = (long) 0;
		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				tx = session.beginTransaction();
			 count = getDataCount(session ,className);
			
			} catch (Exception e) {
				LOG.error("getDataCount:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		
		return count;
	}
	/**
	 * 统计所有数据数量
	 * @param session
	 * @param className
	 * @return
	 */
	protected Long getDataCount(Session session ,@NotNull String className) {
		String hql =MyDBUtil._SELECT.concat("count(*)").concat(MyDBUtil._FROM).concat(className);
		Long count = (Long) session.createQuery(
				"select count(*) from " + className)// 统计条数
				.uniqueResult();
		return count;
	}
	
	public boolean updateData(String className,String attr,String value,@NotNull String[] whereName , @NotNull String[] whereValue , boolean isUseAnd) {

		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				tx = session.beginTransaction();
				Query query = session.createQuery(
						creatUpdateHql(className, attr, value, whereName, whereValue, isUseAnd)
						);  
		        query.executeUpdate();  
				tx.commit();
				return true;
			} catch (Exception e) {
				LOG.error("updateData:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return false;
	}
	public boolean updateData(Object data) {

		if (sessionFactory != null) {
			session = sessionFactory.openSession();
			try {
				tx = session.beginTransaction();
				session.update(data);
				tx.commit();
				return true;
			} catch (Exception e) {
				LOG.error("updateData:",e);
				e.printStackTrace();
				MyDBUtil.rollBack(tx);

			} finally {
				MyDBUtil.closeSession(session, tx);
			}
		}
		return false;
	}
	protected String creatUpdateHql(String className,String attr,String value,@NotNull String[] whereName , @NotNull String[] whereValue , boolean isUseAnd) {
		StringBuilder hql = new StringBuilder();  
				hql.append(MyDBUtil._UPDATE)
				.append(className)
				.append(MyDBUtil._SET)
				.append(attr)
				.append(MyDBUtil._EQUALS)
				.append(value);
		return hql.append(creatWhereHql(whereName, whereValue, isUseAnd)).toString();
	}
	protected String creatUpdateHql(String className,String[] attrs,String[] values,@NotNull String[] whereName , @NotNull String[] whereValue , boolean isUseAnd) {
		StringBuilder hql = new StringBuilder();  
				hql.append(MyDBUtil._UPDATE)
				.append(className)
				.append(MyDBUtil._SET);
				for(int i = 0; i < attrs.length; i++){
					hql.append(attrs[i])
					.append(MyDBUtil._EQUALS)
					.append(values[i]);
				}
				
		return hql.append(creatWhereHql(whereName, whereValue, isUseAnd)).toString();
	}
	// public static class ModeClassEnum{
	// public static final Class BlogArticle =
	// cn.whdreamblog.entites.BlogArticle.class;
	// public static final Class Message = cn.whdreamblog.entites.Message.class;
	// public static final Class User = cn.whdreamblog.entites.User.class;
	// }
}
